﻿(function (host) {
    'use strict';

    if (host.Xjs) {
        return; // It was already loaded
    }

    console.log('Entering app module');

    // Dictionary to store the count of generated ids per type
    var ids = {},

    // Dictionary to store the types mapped by the type string
    types = {},

    // Dictionary to store the instances of the components mapped by their ids
    components = {};

    // Modules can be re-entrant therefore we need
    host.Xjs = {

        // Generates an id based on a type
        generateId: function (type) {

            if (!ids[type]) {
                ids[type] = 0;
            }

            return type + (++ids[type]);
        },

        // Registers a type mapped by the type string
        registerType: function (ctor) {

            var type = ctor.prototype.type;

            console.log('Registering type: ' + type);

            types[type] = ctor;
        },

        // Retrieves the registered type
        getType: function (type) {
            return types[type];
        },

        // Creates an instance of a component using its type, configuration and parent
        create: function (type, conf, parent) {
            var ctor = this.getType(type);

            if (!ctor) {
                throw 'Must include module for type: ' + type;
            }

            return new ctor(conf, parent);
        },

        // Registers the instance of the component to allow its retrieval anywhere by its id
        register: function (cmp) {

            var id = cmp.id;

            if (components[id]) { // Check for unique ids of the registered components
                throw 'Already registered component of id: ' + id;
            }

            console.log('Registering component with id: ' + id);

            components[id] = cmp;
        },

        // Removes a component from the hash of components
        remove: function (cmp) {

            var id = cmp.id;

            if (components[id]) { // Check for unique ids of the registered components

                console.log('Removing component with id: ' + id);
                delete components[id];
            }
        },

        // Retrieves the component by its id
        get: function (id) {
            return components[id];
        },

        // Set the base path for the page
        basePath: '/Scripts/Xjs',

        // Theme support
        themesFolder: '/themes',
        // The default name of the teme
        defaultTheme: 'base',

        loadTheme: function (name) {
            var url = this.basePath + this.themesFolder + '/' + name + '/main.css';
            this.loadCss(url);
        },

        // Dynamically loads a stylesheet
        loadCss: function (url) {

            var lnk = document.createElement('link');
            lnk.setAttribute('rel', 'stylesheet');
            lnk.setAttribute('type', 'text/css');
            lnk.setAttribute('href', url);

            document.getElementsByTagName('head')[0].appendChild(lnk);
        },

        // Selection support
        // The collection of selected components, (to allow multiple selection)
        selected: [],

        // Adds a component to the list of selected ones
        // If keepPrevious is falsy, the previous selection are removed and the unselect method called
        select: function (cmp, keepPrevious) {

            if (!keepPrevious) {

                this.selected.forEach(function (c) {
                    c.deselect(); // Call deselect
                });

                this.selected.length = 0; // Clear the array
            }

            this.selected.push(cmp);
        }
    };

    host.Xjs.loadTheme('base');

})(window);